package sparsearray;

import java.io.*;
import java.util.Arrays;

/**
 * Created by IntelliJ IDEA.
 * User: 杰哥
 * Date: 2020/3/16
 * Time: 19:59
 * 稀疏数组
 */
public class SparseArray {
    public static void main(String[] args) {
        //1.创建一个原始的二维数组 11*11
        //0:表示没有棋子， 1表示黑子，2表示白子
        int chessArr1[][] = new int[11][11];
        chessArr1[1][2] = 1;
        chessArr1[2][3] = 2;

        int sum = 0; /*记录有多少课棋子*/
        for (int[] ints : chessArr1) {
            for (int anInt : ints) {
                if(anInt != 0) {
                    sum++;
                }
            }
        }
        System.out.println("棋子数:"+sum);

        //2.创建对应的稀疏数组
        int sparseArr[][] = new int[sum + 1][3];
        // 给稀疏数组赋值
        sparseArr[0][0] = 11;//稀疏数组第一行第一列记录原始数组有多少行
        sparseArr[0][1] = 11;// 记录列
        sparseArr[0][2] = sum; //记录有多少个值(棋子)

        // 遍历二维数组，将非0的值放到sparseArr中
        int count = 1; //count 用于记录是第几个非0数据
        for(int i = 0; i < 11; i++) {
            for(int j = 0; j < 11; j++) {
                if(chessArr1[i][j] != 0) {
                    sparseArr[count][0] = i;
                    sparseArr[count][1] = j;
                    sparseArr[count][2] = chessArr1[i][j];
                    count++;
                }
            }
        }

        //输出稀疏数组的形式
        System.out.println("行(row)    列(col)     值");
        for(int i = 0; i < sparseArr.length; i++)
            System.out.println(sparseArr[i][0] + "\t\t\t" + sparseArr[i][1] + "\t\t"+sparseArr[i][2]+"\t\n");
        /*行(row)    列()     值
            11			11		2

            1			2		1

            2			3		2
        这个稀疏数组表示对应的原始二维数组有 11行11列，
        其中行(row)下标1列下标(col)2 的值为 1
           行(row)下标2列下标(col)3 的值为 2
        */
        /***************************************************/

        //将稀疏数组 -->  恢复 原始的二维数组
        //1.先读取稀疏数组的第一行，根据第一行的数据，创建原始二维数组

        int  chessArr2[][] = new int[sparseArr[0][0]][sparseArr[0][1]];

        //2.再读取稀疏数组后几行的数据（从第二行开始），并赋值给原始的二维数组
        for(int i = 1; i < sparseArr.length; i++) {
            chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }

        //输出恢复后的二维数组
        System.out.println("恢复后的二维数组:");
        Arrays.stream(chessArr2).forEach(i -> {
            Arrays.stream(i).forEach(n -> System.out.print(n+"\t"));
            System.out.println();
        });
        System.out.println("----------------------------------------------");

//        saveSparseArray(sparseArr, "D:\\三次元\\arr.text");
        int[][] chessArr = readSparseArr(new File("D:\\三次元\\arr.text"));
        Arrays.stream(chessArr).forEach(i -> {
            Arrays.stream(i).forEach(n -> System.out.print(n+"\t"));
            System.out.println();
        });
    }

    /**
     * 稀疏数组保存到磁盘
     */
    public static void saveSparseArray(int[][] arr, String path) {
        File file = new File(path);
        OutputStream out = null;
        PrintWriter printWriter = null;
        try {
            out = new FileOutputStream(file);
            printWriter = new PrintWriter(out);
            int len = arr.length;
            for (int i = 0; i < len; i++) {
                printWriter.println(arr[i][0] + "\t" +arr[i][1] + "\t"+ arr[i][2]);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null != printWriter) {
                printWriter.close();
            }
            if(null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 将文件中的稀疏数组转换为原始的二维数组
     */
    public static int[][] readSparseArr(File file) {
        int[][] result = null;
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(file));
            String data;
            StringBuilder arrData = new StringBuilder();
            while ((data = bufferedReader.readLine()) != null) {
                arrData.append(data + "|");
            }
            String[] strings = arrData.toString().split("\\|");
            /**
             * 在Java.lang包中有String.split()方法，返回是一个数组
             * 我在应用中用到一些，给大家总结一下，仅供大家参考：
             * 1、如果用“.”作为分隔的话，必须是如下写法：String.split(“\.”),这样才能正确的分隔开，不能用String.split(“.”);
             * 2、如果用“|”作为分隔的话，必须是如下写法：String.split(“\|”),这样才能正确的分隔开，不能用String.split(“|”);
             * “.”和“|”都是转义字符，必须得加”\”;
             * 3、如果在一个字符串中有多个分隔符，可以用“|”作为连字符，比如：“acount=? and uu =? or n=?”,把三个都分隔出来，可以用String.split(“and|or”);
             * ————————————————
             * 版权声明：本文为CSDN博主「流风雨情」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。
             * 原文链接：https://blog.csdn.net/qq_29232943/article/details/77132034
             *
             */
//            for (String s : strings) {
//                System.out.print(s);
//            }
            String[] v= strings[0].split("\t");

            result = new int[Integer.parseInt(v[0])][Integer.valueOf(v[0])];

            for (int i = 1; i < strings.length; i++) {
                String[] vv = strings[i].split("\t");
                result[Integer.valueOf(vv[0])][Integer.valueOf(vv[1])] = Integer.valueOf(vv[2]);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != bufferedReader){
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }


}
